﻿using System.Collections.Generic;
using System.Collections.Immutable;
using System.Linq;
using Microsoft.CodeAnalysis;
using Microsoft.CodeAnalysis.CSharp.Syntax;

namespace AutoCADDotNetLibrary.Generator.Receiver
{
    public class CommandMethodAttributeSyntaxReceiver : ISyntaxContextReceiver
    {
        public List<ITypeSymbol> Types { get; } = new List<ITypeSymbol>();

        private List<ITypeSymbol> _commandClassAttributeValue = new List<ITypeSymbol>();
        public void OnVisitSyntaxNode(GeneratorSyntaxContext context)
        {
            //得到[assembly: CommandClass(Type)]参数值
            if (_commandClassAttributeValue.Count == 0)
            {
                ImmutableArray<AttributeData> atts = context.SemanticModel.Compilation.Assembly.GetAttributes();
                foreach (AttributeData att in atts)
                {
                    if (att.AttributeClass.ToDisplayString() == "Autodesk.AutoCAD.Runtime.CommandClassAttribute")
                    {
                        _commandClassAttributeValue.Add(att.ConstructorArguments[0].Value as ITypeSymbol);
                    }
                }
            }

            if (context.Node is ClassDeclarationSyntax classDeclarationSyntax)
            {
                //带有命令的类
                MethodDeclarationSyntax methodDeclarationSyntax = classDeclarationSyntax.Members.OfType<MethodDeclarationSyntax>()
                    .Where(x => x.AttributeLists.Count > 0).Where(x =>
                    {
                        IMethodSymbol ms = context.SemanticModel.GetDeclaredSymbol(x) as IMethodSymbol;

                        //得到有命令的类型
                        return ms.GetAttributes().Any(ad => ad.AttributeClass.ToDisplayString() == "Autodesk.AutoCAD.Runtime.CommandMethodAttribute");
                    }).FirstOrDefault();

                if (methodDeclarationSyntax == null)
                    return;

                ITypeSymbol ts = context.SemanticModel.GetDeclaredSymbol(classDeclarationSyntax) as ITypeSymbol;

                //没有写的,记录下
                if (_commandClassAttributeValue.All(x => !x.Equals(ts, SymbolEqualityComparer.Default)))
                {
                    Types.Add(ts);
                }
            }
        }
    }
}
